import 'package:bilibili/const/Const.dart';
import 'package:bilibili/navigator/bottom_navigator.dart';
import 'package:bilibili/page/login_page.dart';
import 'package:bilibili/page/registration_page.dart';
import 'package:bilibili/page/theme_toggle_page.dart';
import 'package:bilibili/page/video_detail_page.dart';
import 'package:bilibili/provider/theme_provider.dart';
import 'package:bilibili/util/toast.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hi_cache/hi_cache.dart';
import 'package:provider/provider.dart';

import 'http/model/video_model.dart';
import 'navigator/hi_navigator.dart';

void main() {
  runApp(const BiliApp());
}

class BiliApp extends StatefulWidget {
  const BiliApp({super.key});

  @override
  State<StatefulWidget> createState() {
    return _BiliAppState();
  }
}

class _BiliAppState extends State<BiliApp> {
  final BiliRouteDelegate _routeDelegate = BiliRouteDelegate();

  final BiliRouteInformationParser _routeInformationParser =
      BiliRouteInformationParser();

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var _router = Router(
      routeInformationParser: _routeInformationParser,
      routerDelegate: _routeDelegate,
      routeInformationProvider: PlatformRouteInformationProvider(
          initialRouteInformation: RouteInformation(uri: Uri.parse("/"))),
    );

    return FutureBuilder<HiCache>(
        future: HiCache.preInit(),
        builder: (context, snapshot) {
          var widget = snapshot.connectionState == ConnectionState.done
              ? _router
              : const Scaffold(
                  body: Center(
                    child: CircularProgressIndicator(),
                  ),
                );

          return MultiProvider(
            providers: [ChangeNotifierProvider(create: (_) => ThemeProvider())],
            child: Consumer<ThemeProvider>(
              builder: (BuildContext context, ThemeProvider provider,
                  Widget? child) {
                return MaterialApp(
                  home: widget,
                  darkTheme: provider.getTheme(isDark: true),
                  themeMode: provider.mode,
                  theme: provider.getTheme(),
                );
              },
            ),
          );
        });
  }
}

class BiliRouteDelegate extends RouterDelegate<BiliRoutePath>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin {
  @override
  final GlobalKey<NavigatorState> navigatorKey;

  BiliRouteDelegate() : navigatorKey = GlobalKey<NavigatorState>() {
    HiNavigator.getInstance().registerJumpListener(
        RouteJumpListener(onJumpTo: (RouteStatus routeStatus, {Map? args}) {
      _routeStatus = routeStatus;
      if (routeStatus == RouteStatus.detail) {
        vid = args?[Const.VIDEO_ID];
        videoModel = args?[Const.VIDEO_MODEL];
      }
      notifyListeners();
    }));
  }

  //存放页面
  List<MaterialPage> pages = [];
  VideoModel? videoModel;
  String? vid;
  late BiliRoutePath _path;
  RouteStatus _routeStatus = RouteStatus.home;

  @override
  Widget build(BuildContext context) {
    var index = getPageIndex(pages, routeStatus);
    List<MaterialPage> tmpPages = pages;
    if (index != -1) {
      //要打开的页面在栈中已经存在，则将该页面和它上面的所有页面进行出栈
      //tips 具体规则可以根据需要进行调整，这里要求栈中只允许有一个同样的页面的实例
      tmpPages = pages.sublist(0, index);
    }

    var page;
    if (routeStatus == RouteStatus.home) {
      pages.clear();
      page = pageWrap(const BottomNavigator(), "BottomNavigator");
    } else if (routeStatus == RouteStatus.detail) {
      page = pageWrap(
          VideoDetailPage(
            videoModel: videoModel,
            vid: vid!,
          ),
          "detail");
    } else if (routeStatus == RouteStatus.registration) {
      page = pageWrap(RegistrationPage(), "注册页");
    } else if (routeStatus == RouteStatus.login) {
      page = pageWrap(LoginPage(), "登录页");
    } else if (routeStatus == RouteStatus.theme) {
      page = pageWrap(const ThemeTogglePage(), "暗黑模式");
    }

    // 重新创建一个堆栈的数组，否则pages因引用没有改变路由而不会生效
    tmpPages = [...tmpPages, page];

    HiNavigator hiNavigator = HiNavigator.getInstance();
    hiNavigator.notify(tmpPages, pages);

    pages = tmpPages;

    if (kDebugMode) {
      print("build pages length is : ${pages.length}");
    }

    return WillPopScope(
        onWillPop: () async =>
            !(await navigatorKey.currentState?.maybePop() ?? false),
        child: Navigator(
          key: navigatorKey,
          pages: pages,
          onPopPage: (route, result) {
            if (route.settings is MaterialPage) {
              var child = (route.settings as MaterialPage).child;
              if (child is LoginPage) {
                if (!hasLogin) {
                  showToast("请先登录！");
                  return false;
                }
              }
            }

            //在这里控制是否可以返回
            if (!route.didPop(result)) {
              return false;
            }

            var tempPages = [...pages];
            pages.removeLast();
            //通知路由发生变化
            HiNavigator.getInstance().notify(pages, tempPages);

            return true;
          },
        ));
  }

  RouteStatus get routeStatus {
    if (_routeStatus != RouteStatus.registration && !hasLogin) {
      _routeStatus = RouteStatus.login;
    } else if (videoModel != null) {
      _routeStatus = RouteStatus.detail;
    }
    return _routeStatus;
  }

  bool get hasLogin =>
      HiCache.getInstance().get(Const.BOARDING_PASS) == null ? false : true;

  @override
  Future<void> setNewRoutePath(BiliRoutePath configuration) async {
    _path = configuration;
  }
}

class BiliRouteInformationParser extends RouteInformationParser<BiliRoutePath> {
  @override
  Future<BiliRoutePath> parseRouteInformation(
      RouteInformation routeInformation) async {
    var uri = routeInformation.uri;
    if (kDebugMode) {
      print('uri: $uri');
    }

    if (uri.pathSegments.isEmpty) {
      return BiliRoutePath.home();
    }

    return BiliRoutePath.detail();
  }
}

//定义路由的数据
class BiliRoutePath {
  final String location;

  BiliRoutePath.home() : location = '/';

  BiliRoutePath.detail() : location = "/detail";

  BiliRoutePath.theme() : location = "/theme";
}
